package cn.tedu.csmall.product.webapi.service;

import cn.tedu.csmall.common.ex.ServiceException;
import cn.tedu.csmall.common.web.State;
import cn.tedu.csmall.pojo.dto.CategoryAddNewDTO;
import cn.tedu.csmall.pojo.dto.CategoryBaseInfoDTO;
import cn.tedu.csmall.pojo.dto.CategoryDisPlayDTO;
import cn.tedu.csmall.pojo.dto.CategoryEnableDTO;
import cn.tedu.csmall.pojo.entity.Category;
import cn.tedu.csmall.pojo.vo.CategoryDetailsVO;
import cn.tedu.csmall.pojo.vo.CategorySimpleListItemVO;
import cn.tedu.csmall.pojo.vo.CategorySimpleVO;
import cn.tedu.csmall.product.service.ICategoryService;
import cn.tedu.csmall.product.webapi.mapper.CategoryMapper;
import cn.tedu.csmall.product.webapi.repository.ICategoryRedisRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;

@Service
@Slf4j
public class CategoryServiceImpl implements ICategoryService {
    @Autowired
    CategoryMapper categoryMapper;
    @Autowired
    ICategoryRedisRepository categoryRedisRepository;

    @Override
    // 注意：需要创建异常
    // 注意：需要在CategoryMapper中补充getById()方法，至少返回：depth
    // 注意：需要在CategoryMapper中补充updateIsParentById()方法
    public void add(CategoryAddNewDTO categoryAddNewDTO) {
        // 从参数中取出尝试添加的类别的名称
        String name = categoryAddNewDTO.getName();
        // 调用categoryMapper.getByName()方法查询
        // 判断查询结果是否不为null
        // 是：抛出ServiceException
        if (categoryMapper.getByName(name) != null) {
            throw new ServiceException(State.ERR_CATEGORY_NAME_DUPLICATE,"用户名已存在");
        }
        // 从参数中取出父级类别的id：parentId
        Long parentId = categoryAddNewDTO.getParentId();
        // 判断parentId是否为0,当前尝试新增的类别depth默认为1
        Integer depth = 1;
        CategorySimpleVO parentCategory = null;
        if (parentId != 0) {
            // 否：此次尝试添加的不是一级类别，则应该存在父级类别，调用categoryMapper.getById()方法查询父级类别的信息
            parentCategory = categoryMapper.getById(parentId);
            // -- 判断查询结果是否为null
            // -- 是：抛出ServiceException
            if (parentCategory == null) {
                throw new ServiceException(State.ERR_CATEGORY_NOT_FOUND,"添加失败 父级类别不存在");
            }
            // -- 否：当前depth >>> 是父级depth + 1
            depth = parentCategory.getDepth() + 1;
        }

        // 创建Category对象
        Category category = new Category();
        // 调用BeanUtils.copyProperties()将参数对象中的属性值复制到Category对象中
        BeanUtils.copyProperties(categoryAddNewDTO, category);
        // 补全Category对象中的属性值：depth >>> 前序运算结果
        category.setDepth(depth);
        // 补全Category对象中的属性值：enable >>> 1（默认即启用）
        category.setEnable(1);
        // 补全Category对象中的属性值：isParent >>> 0
        category.setIsParent(0);
        // 补全Category对象中的属性值：gmtCreate, gmtModified >>> LocalDateTime.now()
        LocalDateTime now = LocalDateTime.now();
        category.setGmtCreate(now);
        category.setGmtModified(now);
        // 调用categoryMapper.insert(Category)插入类别数据，获取返回的受影响的行数
        int rows = categoryMapper.insert(category);
        // 判断返回的受影响的行数是否不为1
        if (rows != 1) {
            // 是：抛出ServiceException
            throw new ServiceException(State.ERR_INSERT,"插入数据异常");
        }
        // 判断父级类别的isParent是否为0
        // 是：调用categoryMapper.updateIsParentById()方法，将父级类别的isParent修改为1，获取返回的受影响的行数
        if (parentCategory != null && parentCategory.getIsParent() == 0) {
            int row = categoryMapper.updateIsParentById(parentId, 1);
            // 判断返回的受影响的行数是否不为1
            // 是：抛出ServiceException
            if (row != 1) {
                throw new ServiceException(State.ERR_UPDATE,"添加类别失败 服务器繁忙");
            }
        }
    }

    @Override
    public void delete(Long id) {
        //根据id获取当前详细类别信息
        CategoryDetailsVO category = categoryMapper.getDetailsById(id);
        //根据客户端id判断是否存在该类别 不存在则抛出异常
        if (category==null){
            throw new ServiceException(State.ERR_CATEGORY_NOT_FOUND,"类别不存在");
        }
        if(category.getIsParent()==1){
            throw new ServiceException(State.ERR_CATEGORY_IS_PARENT,"有子级类别,不能随便删除");
        }
        //获取当前类别的父级id
        Long parentId = category.getParentId();
        //判断当前类别是父级类别中的最后一个类别
        if(categoryMapper.getCountByParentId(parentId)==1){
            categoryMapper.delete(id);
            //修改父级类别的isParent为0
            categoryMapper.updateIsParentById(parentId,0);
            return;
        }
        categoryMapper.delete(id);
    }


    @Override
    public List<CategorySimpleListItemVO> listByParentId(Long parentId) {
        return categoryMapper.listByParentId(parentId);
    }

    @Override
    public CategoryDetailsVO getDetailsById(Long id) {
        CategoryDetailsVO category = categoryMapper.getDetailsById(id);
        if (category==null){
            throw new ServiceException(State.ERR_CATEGORY_NOT_FOUND,"获取类别失败，数据不存在");
        }
        return category;
    }

    @Override
    public void updateEnable(CategoryEnableDTO categoryEnableDTO) {
        //获取客户端传递的id并根据id查询类型是否存在
        Long id = categoryEnableDTO.getId();
        if (categoryMapper.getDetailsById(id)==null){
            throw new ServiceException(State.ERR_CATEGORY_NOT_FOUND,"该类别不存在");
        }

        Integer enable = categoryEnableDTO.getEnable();

        //查询数据库是否启用状态
        Integer resultEnable = categoryMapper.getDetailsById(id).getEnable();

        //判断禁用状态冲突时抛出异常
        if (enable.equals(resultEnable)&&enable==0){
            throw new ServiceException(State.ERR_CATEGORY_ENABLE,"禁用状态冲突");
        }
        //判断启用状态冲突时抛出异常
        if (enable.equals(resultEnable)&&enable==1){
            throw new ServiceException(State.ERR_CATEGORY_ENABLE,"启用状态冲突");
        }
        categoryMapper.updateEnableById(id,enable);
    }

    @Override
    public void updateIsDisplay(CategoryDisPlayDTO categoryDisPlayDTO) {
        //获取客户端id查询类别是否存在否则抛出异常
        Long id = categoryDisPlayDTO.getId();
        if (categoryMapper.getDetailsById(id)==null){
            throw new ServiceException(State.ERR_CATEGORY_NOT_FOUND,"类别不存在");

        }
        //获取客户端的isDisplay
        Integer isDisplay = categoryDisPlayDTO.getIsDisplay();
        //获取数据库的isDisplay
        Integer resIsDisplay = categoryMapper.getDetailsById(id).getIsDisplay();
        //判断如果显示与否状态冲突则抛出异常
        if (resIsDisplay.equals(isDisplay) && isDisplay==0){
            throw new ServiceException(State.ERR_CATEGORY_IS_DISPLAY,"隐藏状态冲突");
        }
        if (resIsDisplay.equals(isDisplay) && isDisplay==1){
            throw new ServiceException(State.ERR_CATEGORY_IS_DISPLAY,"显示状态冲突");
        }
        categoryMapper.updateIsDisplayById(id,isDisplay);
    }

    @Override
    public void updateBaseInfo(CategoryBaseInfoDTO categoryBaseInfoDTO) {
        //根据用户传递的id判断类别是否存在
        //否则抛出异常
        if(categoryMapper.getDetailsById(categoryBaseInfoDTO.getId())==null){
            throw new ServiceException(State.ERR_CATEGORY_NOT_FOUND,"类别不存在");
        }
        //判断如果存在相同名称则抛出异常
        if(categoryMapper.getCountByName(categoryBaseInfoDTO.getName())!=0){
            throw new ServiceException(State.ERR_BAD_REQUEST,"该名称已被占用");
        }
        categoryMapper.updateBaseInfoById(categoryBaseInfoDTO.getId(), categoryBaseInfoDTO.getName(),
                categoryBaseInfoDTO.getKeywords(), categoryBaseInfoDTO.getSort(),
                categoryBaseInfoDTO.getIcon());
    }

    @Override
    public void preloadCache() {
        log.debug("删除缓存中的类别列表……");
        categoryRedisRepository.deleteList();
        log.debug("删除缓存中的各独立的类别数据……");
        categoryRedisRepository.deleteAllItem();

        log.debug("从数据库查询类别列表……");
        List<CategoryDetailsVO> list = categoryMapper.list();

        for (CategoryDetailsVO category : list) {
            log.debug("查询结果：{}", category);
            log.debug("将当前类别存入到Redis：{}", category);
            categoryRedisRepository.save(category);
        }

        log.debug("将类别列表写入到Redis……");
        categoryRedisRepository.save(list);
        log.debug("将类别列表写入到Redis完成！");
    }


}
